#include "Reactor/TcpConnection.h"
#include "Reactor/EchoServer.h"
#include "KeyRecommander.hh"
#include "nlohmann/json.hpp"
#include "web/WebPageQuery.hh"
#include "web/WebPageSearcher.hh"
#include "Cache/SingnalRedis.hh"
#include "Cache/CacheManager.hh"
#include "Log/Log.hh"

#include <iostream>
#include <functional>
#include <iomanip>
#include <cstdlib>
#include <string.h>
#include <thread>
#include <pthread.h>
#include <mutex>

using std::cout;
using std::endl;
using std::bind;
using std::this_thread::get_id;
using std::thread;
using std::mutex;
using std::unique_lock;

MyTask::MyTask(const string &msg, const TcpConnectionPtr &con)
: _msg(msg)
, _con(con)
{

}

void MyTask::process()
{
    // 查询 Cache
    // 访问自己的 Cache要加锁
    thread::id p_id = get_id();
    Log::info("此次的工作线程是: %lld", get_id());

    auto pid_vec = CacheManager::createCacheManager()->getPidVec();
    size_t serial = 0;
    for(; serial < pid_vec.size(); ++serial){
        if(pid_vec[serial] == p_id){
            break;
        }
    }

    {
        unique_lock<mutex> ul(CacheManager::createCacheManager()->getLocks()[serial]);
        Log::debug("对 %lld 号缓存加锁", serial);
        // cout << "对" << serial << " 号线程的缓存加锁\n";
        string json;
        bool hit = CacheManager::createCacheManager()->getCaches()[serial].find(_msg, json);
        if(hit == true){
            Log::info("对 %lld 号缓存命中", serial);
            // cout <<  serial << " 号线程的缓存命中\n";
            _con->sendInLoop(json);
            return;
        }
        Log::info("对 %lld 号缓存未命中", serial);

    }

    // // 查询 redis
    // auto ret = SingnalRedis::createRedis()->getRedis().get(_msg);
    // if(ret){
    //     cout << "redis 命中\n";
    //     _con->sendInLoop(ret.value());
    //     return;
    // }



    // 未命中搜索
    string pre = _msg.substr(0, 3);
    string arg = _msg.substr(3);

    if(pre == "100"){
        KeyRecommander kr(arg, _con);
        kr.execute();
        kr.response();
    }else if(pre == "200"){
        WebPageSearcher wps(arg, _con);
        wps.doQuery();
    }

}

EchoServer::EchoServer(size_t threadNum, size_t queSize
                       , const string &ip
                       , unsigned short port)
: _pool(threadNum, queSize)
, _server(ip, port)
{

}

EchoServer::~EchoServer()
{

}

//服务器的启动与停止
void EchoServer::start()
{
    _pool.start();

    //三个回调放在此处进行注册
    using namespace std::placeholders;
    _server.setAllCallback(bind(&EchoServer::onNewConnection, this, _1)
                           , bind(&EchoServer::onMessage, this, _1)
                           , bind(&EchoServer::onClose, this, _1));
    _server.start();
}

void EchoServer::stop()
{
    _pool.stop();
    _server.stop();
}

//三个回调
void EchoServer::onNewConnection(const TcpConnectionPtr &con)
{
    cout << con->toString() << " 新连接" << endl;
}

void EchoServer::onMessage(const TcpConnectionPtr &con)
{

    string msg = con->receive();

    // 可能发来的是空的
    if(msg.size() == 0){
        con->sendInLoop("{\"code\": 0, \"msg\": \"error\"}");
        return;
    }

    // cout << "msg = " << msg.size() << "\n";
    // if(msg.size() == 0){
    //     con->sendInLoop("{\"code\": 0, \"msg\": \"error\"}");
    //     return;
    // }
    cout << "搜索 >> " << msg << endl;

    MyTask task(msg, con);

    _pool.addTask(bind(&MyTask::process, task));

}

void EchoServer::onClose(const TcpConnectionPtr &con)
{
    cout << con->toString() << " 连接断开!!!" << endl;
}
